package ir;

import org.apache.axis.client.Stub;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;

public abstract class ClassGenerator implements Generator {

  protected Class<Object> underlier;
  private String underlierGeneratedClassName;

  
  public ClassGenerator(Class<Object> underlier) {
    this.underlier =  underlier;
    underlierGeneratedClassName = "Gwt" + underlier.getSimpleName();
  }
  
  public String gen() {
    return null;
  }
  
//Get all the Data Classes used; anything in params or returns
  protected Set<Class<Object>> getRequiredTypes() {
    
     Set<Class<Object>> types = new HashSet<Class<Object>>();
     Method[] methods = underlier.getDeclaredMethods();
     
     String stubName = underlier.getSimpleName();
     
     // get all return types and fields in this stub's methods
     for (int j = 0; j < methods.length; j++  ) {
     
            // do not convert Constructor, private, or static methods.
            int modifiers = methods[j].getModifiers();
            boolean isPub = Modifier.isPublic(modifiers);
            boolean isStatic = Modifier.isStatic(modifiers);
            
//            if (! methods[j].getName().equals(simpleName) && isPub && !isStatic) {
            String methodName = methods[j].getName();
            if (! methodName.equals(stubName) && isPub && ! methodName.contains("axis")) {
              
              types.add((Class<Object>) methods[j].getReturnType());
              Class<Object>[] parameterTypes = (Class<Object>[]) methods[j].getParameterTypes();
              for (int k = 0 ; k < parameterTypes.length; k++)
                types.add(parameterTypes[k]);
            }
      }
     
      return types;
    }
  
  @Override
  public String toString() {
    return underlier.getSimpleName();
  }
  
  @Override
  public int hashCode() {
    return underlier.hashCode();
  }
  
  @Override
  public boolean equals(Object o) {
    return (o.hashCode() == underlier.hashCode());
  }
  
  public abstract Set<DataNode> getRequiredDataNodes();
  public abstract String getPackage();
  
  protected String getImports() {
    
    Set<DataNode> requiredDataNodes = getRequiredDataNodes();
    
    String imports = "";
    
    for (DataNode d : requiredDataNodes) {
      String generatedClassName = d.getGeneratedClassName();
      
      
      // exclude self
      if (generatedClassName != getGeneratedClassName()) {
        String canonicalName = d.getPackage() + "." + generatedClassName;
        String import_statement = "import " + canonicalName + ";\n";
        imports += import_statement;
      }
    }
    
    imports = "import java.io.Serializable;\n" + imports;
//    imports = "import java.util.*;\n" + imports;
    imports = "import java.util.Date;\n" + imports;
    
    return imports;

  }

  public String getGeneratedClassName() {
    return underlierGeneratedClassName;
  }
  
  public Class<Object> getUnderlier() {
    return underlier;
  }


}
